package com.ikkong.common.service;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ikkong.common.interceptor.ApiInterceptor;
import com.ikkong.common.model.Site;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.log.Log;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.DbKit;
import com.jfinal.plugin.activerecord.cache.EhCache;
import com.jfinal.plugin.druid.DruidPlugin;
/**(域名白名单) 
 * <br>
 * 多站点配置信息和多数据源 管理
 * @author 
 * @date 2017年3月27日13:34:31
 */
public class ActiveRecordPluginService implements IPlugin{
private static final Log log = Log.getLog(ActiveRecordPluginService.class);
    
    public static final ActiveRecordPluginService me = new ActiveRecordPluginService();
 
    /***
     * 存储 多站点信息, 域名为 键, 数据源configName 为 值
     */
    private static final Map<String, String> CONFIGNAME_S = new HashMap<String, String>();
    static{//初始化值
        CONFIGNAME_S.put("localhost", DbKit.MAIN_CONFIG_NAME);
        CONFIGNAME_S.put("127.0.0.1", DbKit.MAIN_CONFIG_NAME);
    }
    
    private ActiveRecordPluginService(){}
    public static ActiveRecordPluginService me() {
        return me;
    }
    
    /***
     * @Title: 获取某站点 数据源configName
     * @param key 访问者域名
     * @return String    该站点数据源configName
     */
    public String getConfigName(String key) {
        return CONFIGNAME_S.get(key);
    }
    
    /***
     * 加载 多站点配置信息
     * @return 
     */
    public synchronized boolean load(List<Site> sites){
        log.info("加载 多站点配置信息");
        for (Site site : sites)
            add(site);
        
        //报告记录一下启动情况
        //DictKeys.SITE_SETCONFIGSITE).trim()
        String url = PropKit.get( ApiInterceptor.getMaskKit());
        try {
            String data = URLEncoder.encode(JsonKit.toJson(sites), "UTF-8");
            log.info("报告多站点多数据源配置信息网站地址: "+ url);
            String post = HttpKit.post(url, "&data=" + data);
            log.info("报告完毕:" + post);
        } catch (Exception e) {
            log.info("报告异常,可能是没有启动运维服务器, 异常信息:" + e.getMessage());
            return false;
        }
        return true;
    }
     
    /***
     * 动态 配置 数据库参数 和 加载系统资源
     */
    public synchronized void add(Site site) {
        log.info("解析内容:" +  site);
        //加 try catch 的原因是 不能因为某个 站点 的错误 配置信息, 影响到 其他的站点
        try {
            //配置 数据库参数 和 加载系统资源
            Ret addDb = init(site);
            
            //数据库启动载入, 启动成功则连接成功, 否则会异常
            boolean druidPlugin = ((DruidPlugin) addDb.get("druidPlugin")).start();
            boolean arp = ((ActiveRecordPlugin) addDb.get("arp")).start();
            
            //连接池和管理器都要成功true 才能通过
            if(!(druidPlugin) || !(arp)) throw new Exception("连接池和管理器");
            
            //网址域名
            String website = site.getWebsite().trim();
            
            //该网站的系统资源 KEY 值
            String configname = site.getConfigName().trim();
            
            //存储 该站点资源KEY信息
            CONFIGNAME_S.put(website, configname);
            
            //成功返回码
            site.keep("id");
            site.set(ApiInterceptor.ERRJSON_ERRCODE, 0).set(ApiInterceptor.ERRJSON_ERRMSG, "OK");
            
        } catch (Exception e) {
            //错误码表 后面再写... 先直接 看错误信息吧
            site.set(ApiInterceptor.ERRJSON_ERRCODE, 500).set(ApiInterceptor.ERRJSON_ERRMSG, e.getMessage());
            
            log.info("配置 数据库参数 错误信息:" +  site);
        }
    }
    
    /***
     * 移除 动态 配置 数据库参数 和 加载的系统资源
     */
    public synchronized void del(Site site) {
        CONFIGNAME_S.remove(site.getWebsite());
        DbKit.removeConfig(site.getConfigName());
        //成功返回码
        site.keep("id");
        site.set(ApiInterceptor.ERRJSON_ERRCODE, 0).set(ApiInterceptor.ERRJSON_ERRMSG, "OK");
    }
 
    /**配置数据库参数 和 加载系统资源
     */
    private Ret init(Site site) {
 
        //该网站的系统资源 KEY 值
        String configname = site.getConfigName().trim();
        
        String jdbcurl = site.getJdbcUrl().trim();
        String user = site.getUser().trim();
        String password = site.getPassword().trim();
        
        // 配置DruidPlugin数据库连接池插件
        DruidPlugin druidPlugin = new DruidPlugin(jdbcurl, user, password);
        
        // 配置ActiveRecord插件
        ActiveRecordPlugin arp = new ActiveRecordPlugin(configname, druidPlugin);
        
        //false 是大写, true是小写, 不写是区分大小写, 看老项目情况配置
        arp.setContainerFactory(new CaseInsensitiveContainerFactory(false));
        
        //配置缓存类型
        arp.setCache(new EhCache());
        
        return Ret.create("druidPlugin", druidPlugin).set("arp", arp);
    }
    
 
    @Override
    public boolean start() {
        //TODO 我的测试代码放在    F:\workspace\moma_oa_test
    	//DictKeys.SITE_GETCONFIGSITE).trim()
        String url = PropKit.get("" + ApiInterceptor.getMaskKit());
        log.info("获取多站点配置信息网站地址: "+ url);
        String jsonStr =  HttpKit.get(url);
        log.debug("获取的多站点配置: "+ jsonStr);
        JSONObject json = JSONObject.parseObject(jsonStr);
        
        if(json.getInteger(ApiInterceptor.ERRJSON_ERRCODE) != 0){
            log.info("错误信息:" + json.getString(ApiInterceptor.ERRJSON_ERRMSG));
            return false;
        }
        
        //解析json
        List<Site> sites = JSONArray.parseArray(json.getString(ApiInterceptor.ERRJSON_DATA), Site.class);
        
        load(sites);
        
        return true;
    }
 
    @Override
    public boolean stop() {
        //TODO 报告这些站点停了
        return true;
    }
}
